/*
 * main.cpp
 *
 *  Created on: 04.07.2012
 *      Author: aska
 */

/*
 * Hello, World for Win32
 * gcc winhello.c -o winhello.exe
 */
//#define _WIN32
//#undef _LINUX
#include <windows.h>
//#include <stdio.h>
#include <string>
#include <iostream>
//#include <stdlib.h>
#include "door_control_dll_declarations.h"
#include "test_threads.h"
#include "test_2_thread.h"
#include "Test_3_thread.h"
//#include "main.h"
//#include "ser_port.h"
using namespace std;
//#define macro_str(s) #s
#define ASSIGN_FUNC_FROM_DLL (dll_handler, func_name)  (func_name = ( t_##func_name )GetProcAddress(dll_handler, #func_name ))

door_control_lib * door_control_lib_inst;
//char ser_name[32];
string ser_name;
int ser_baud = 0;
string ping_addr;
int main(int argc, char *argv[])
{
	door_control_lib_inst = new door_control_lib();
	//printf("\nHello!\n");
	cout << endl << "Hello!" << endl;
	//MessageBox(NULL, "Hello, world!", "Hello, world!", MB_OK);
	door_control_lib_inst->door_control_dll_load();
	//door_control_dll_load();
	//ser_port ser_port_inst;
	//strcpy(ser_port_inst.name, "COMx");
	//ser_port_inst.baud = 9600;
	//printf(" port name %s\n", ser_port_inst.name);
	//printf(" port baud %d\n", ser_port_inst.baud);
	//printf("parser start %s\n", "");
	for (int i1 = 0; i1 < argc; i1++)
	{

		//printf("arg %2d : %s ", i1, argv[i1]);
		//if(!strcmp(argv[i1], "--help"))
		if(string(argv[i1]) == string("--help"))
		{
			cout << "Help: "<< endl;
			cout << "wine Door_control_main.exe --init --ser_name COM1 --ser_baud 19200 --ser_open --led1s --led3s --read_key --ser_close --finish" << endl;
			cout << "--init - allocate resources for serial port" << endl;
			cout << "--set_if_mode - set mode: 1 - serial, 2 - d2xx" << endl;
			cout << "--ser_name - serial port name" << endl;
			cout << "--ser_baud - serial port baudrate" << endl;
			cout << "--ser_open - serial port open" << endl;
			cout << "--dev_open - serial port open and check device is properly installed" << endl;
			cout << "--get_drv_ver - get FTDI driver version" << endl;
			cout << "--get_lib_ver - get D2XX library version" << endl;
			cout << "--dev_set_brd_ver- set board version, type version as decimal parameter" << endl;
			cout << "--dev_get_brd_ver - get board version" << endl;
			cout << "--dev_set_ser_no - set serial number, type serial number as 4-characters string XXXX" << endl;
			cout << "--dev_get_ser_no - get serial number" << endl;
			cout << "--lock_open - open lock" << endl;
			cout << "--lock_close - close lock" << endl;
			cout << "--modem_reset - reset modem" << endl;
			cout << "--inps_r - read inputs" << endl;
			cout << "--read_key - wait for typing key" << endl;
			cout << "--ping_addr - set addr to ping" << endl;
			cout << "--ping_start - start to ping" << endl;
			cout << "--ping_stop - stop to ping" << endl;
			cout << "--test_1 - test" << endl;
			cout << "--test_2 - test on periodical get_inps" << endl;
			cout << "--test_3 - run socket" << endl;
			cout << "--ser_close - close serial port" << endl;
			cout << "--finish - freeing resources allocated for serial port" << endl;
			cout << "-- - " << endl;
			/*
			printf(" -p port_name - name of port where device connected, example: -p /dev/ttyUSB0\n");
			printf(" --ddcconf file_name - name of file, where config for DDC stored, example: --ddcconf c_view_roll_self_0.h\n");
		  printf(" --sendall - send all parameters to DDC\n");
		  printf(" --setsector 0xNNNN - set start sector for receiving data, hexadecimal, example: --setsector 0x3dcf\n");
		  printf("--start_time ttt - start record for ttt us, example --start_time 500000\n");
		  printf(" --getsector - get sector, where data writing is finished\n");
		  printf(" --readblocks 0xSSSS 0xNNNN - read from sector № 0xSSSS 0xNNNN blocks\n, example --readblocks 0x500f 0x02\n");
		  printf("below is typical call to send config from file c_view_roll_self_0.h to the device connected to /dev/ttyUSB0,");
		  printf(" setting start sector to 0x3dcf\n");
		  printf("exec -p /dev/ttyUSB0 --ddcconf c_view_roll_self_0.h --sendall --setsector 0x3dcf");
		  printf("below is typical call to send config from file c_view_roll_self_0.h to the device connected to /dev/ttyUSB0,");
		  printf(" getting last sector and reading 2 sectors from sector 0x500f\n");
		  printf("exec -p /dev/ttyUSB0 --ddcconf c_view_roll_self_0.h --getsector --readblocks 0x500f 0x02\n");
			*/
		}

		//TODO: check if dll is loaded

		if(!strcmp(argv[i1], "--init"))
		{
			cout << " init " << door_control_lib_inst->door_control_init() << endl;
		}
		if(!strcmp(argv[i1], "--set_if_mode"))
		{
			int mode = 0;
			if((i1 + 1) <= argc)
			{
				i1++;
				sscanf(argv[i1], "%d", &mode);
				//ser_port_inst.set_baud(baud);
				door_control_lib_inst->door_control_dev_if_mode(mode);
			}
			//printf(" ser_baud %d\n", ser_port_inst.get_baud());
			cout << " if mode " << mode << endl;
		}
		if(!strcmp(argv[i1], "--ser_name"))
		{
			if (door_control_lib_inst->door_control_ser_set_name <= 0)
				cout << " " << argv[i1] << " uninitialized" << endl;
			else
			{
				if((i1 + 1) <= argc)
				{
					i1++;
					//strcpy(ser_port_inst.name, argv[i1]);
					door_control_lib_inst->door_control_ser_set_name(argv[i1]);
					//strcpy(ser_name, argv[i1]);
					ser_name = string(argv[i1]);
				}
				//cout << " ser_name %s\n", ser_port_inst.name);
				cout << " ser_name " << argv[i1] << endl;
			}
		}
		if(!strcmp(argv[i1], "--ser_baud"))
		{
			if (door_control_lib_inst->door_control_ser_set_baud <= 0)
				cout << " " << argv[i1] << " uninitialized" << endl;
			else
			{
				int baud = 0;
				if((i1 + 1) <= argc)
				{
					i1++;
					sscanf(argv[i1], "%d", &baud);
					//ser_port_inst.set_baud(baud);
					door_control_lib_inst->door_control_ser_set_baud(baud);
					ser_baud = baud;
				}
				//printf(" ser_baud %d\n", ser_port_inst.get_baud());
				cout << " ser_baud " << door_control_lib_inst->door_control_ser_get_baud() << endl;
			}
		}
		if(!strcmp(argv[i1], "--ser_open"))
		{
			if (door_control_lib_inst->door_control_ser_open <= 0)
				cout << argv[i1] << " uninitialized" << endl;
			else
			{
				char buf_str[63];
				int ret_len = 0;
				//int ret_val = ser_port_inst.open();
				int ret_val = door_control_lib_inst->door_control_ser_open();
				cout << " ser_open " << ret_val << endl;
				//Sleep(1000);
				//ret_val = ser_port_inst.read_buf(buf_str, &ret_len, 63);
				//ret_val = door_control_lib_inst->door_control_ser_read_buf(buf_str, &ret_len, 63);
				cout << "  open received len " << ret_len << endl;
				cout << "  open received str " << buf_str << endl;
			}
		}
		if(!strcmp(argv[i1], "--dev_open"))
		{
			if (door_control_lib_inst->door_control_dev_open <= 0)
				cout << argv[i1] << " uninitialized" << endl;
			else
			{
				//char buf_str[63];
				//int ret_len = 0;
				//int ret_val = ser_port_inst.open();
				int ret_val = door_control_lib_inst->door_control_dev_open();
				cout << " ser_open " << ret_val << endl;
				Sleep(1000);
				//ret_val = ser_port_inst.read_buf(buf_str, &ret_len, 63);
				//ret_val = door_control_lib_inst->door_control_ser_read_buf(buf_str, &ret_len, 63);
				//printf("  open received len %d\n", ret_len);
				//printf("  open received str %s\n", buf_str);
				if (ret_val == 0)
					cout << "device opened" << endl;
				else
					cout << "unable to open device" << endl;
			}
		}
		if(!strcmp(argv[i1], "--get_drv_ver"))
		{
			int ret_val = 0;
			unsigned int var_drv_ver = 0;
			ret_val = door_control_lib_inst->door_control_ft_get_driver_version(&var_drv_ver);
			if (ret_val == 0)
				cout << "driver version  : " << hex << var_drv_ver << endl;
			else
				cout << argv[i1] << " error " << ret_val << endl;
		}
		if(!strcmp(argv[i1], "--get_lib_ver"))
		{
			int ret_val = 0;
			unsigned int var_lib_ver = 0;
			ret_val = door_control_lib_inst->door_control_ft_get_library_version(&var_lib_ver);
			if (ret_val == 0)
				cout << "library version : " << hex << var_lib_ver << endl;
			else
				cout << argv[i1] << " error " << ret_val << endl;
		}
		if(!strcmp(argv[i1], "--dev_set_brd_ver"))
		{
			if (door_control_lib_inst->door_control_set_brd_ver <= 0)
				cout << argv[i1] << " uninitialized" << endl;
			else
			{
				i1++;
				char dev_brd_ver = 0;
				sscanf(argv[i1], "%d", (int*)(&dev_brd_ver));
				//strcpy(dev_ser_no, argv[i1]);
				cout << "Board version set to " << dev_brd_ver << " result is ";
				//char buf_str[63];
				//int ret_len = 0;
				//int ret_val = ser_port_inst.open();
				int ret_val = door_control_lib_inst->door_control_set_brd_ver(dev_brd_ver);
				cout << ret_val << endl;
				dev_brd_ver = 0;
				if (door_control_lib_inst->door_control_get_brd_ver == 0)
					cout << " door_control_get_brd_ver uninitialized" << endl;
				else
				{
					ret_val = door_control_lib_inst->door_control_get_brd_ver(&dev_brd_ver);
					cout << "get board version  " << ret_val << ", board version: " << dev_brd_ver << endl;
				}
			}
		}
		if(!strcmp(argv[i1], "--dev_get_brd_ver"))
		{
			if (door_control_lib_inst->door_control_get_brd_ver <= 0)
				cout << " " << argv[i1] << " uninitialized" << endl;
			else
			{
				char dev_brd_ver = 0;
				int ret_val = door_control_lib_inst->door_control_get_brd_ver(&dev_brd_ver);
				cout << "get board version  " << ret_val << ", board version: " << dev_brd_ver << endl;
			}
		}
		if(!strcmp(argv[i1], "--dev_set_ser_no"))
		{
			if (door_control_lib_inst->door_control_get_ser_no <= 0)
				cout << " " << argv[i1] << " uninitialized" << endl;
			else
			{
				i1++;
				char dev_ser_no[4];
				strcpy(dev_ser_no, argv[i1]);
				cout << "Serial number set to " << dev_ser_no << ", result is ";
				//char buf_str[63];
				//int ret_len = 0;
				//int ret_val = ser_port_inst.open();
				int ret_val = door_control_lib_inst->door_control_set_ser_no(dev_ser_no);
				cout << ret_val << endl;
				ret_val = door_control_lib_inst->door_control_get_ser_no(dev_ser_no, 4);
				cout << "get serial number  " << ret_val << ", ser_No: " << dev_ser_no << endl;
			}
		}
		if(!strcmp(argv[i1], "--dev_get_ser_no"))
		{
			if (door_control_lib_inst->door_control_get_ser_no <= 0)
				cout << " " << argv[i1] << " uninitialized" << endl;
			else
			{
				char dev_ser_no[4];
				//int ret_len = 0;
				int ret_val = door_control_lib_inst->door_control_get_ser_no(dev_ser_no, 4);
				cout << "get serial number  " << ret_val << ", ser_No: " << dev_ser_no << endl;
			}
		}

		if(!strcmp(argv[i1], "--led1s"))
		{
			//ser_port_inst.led_set(1, 1);
			door_control_lib_inst->door_control_leds_set(1, 1);
		}
		if(!strcmp(argv[i1], "--led1c"))
		{
			//ser_port_inst.led_set(1, 0);
			door_control_lib_inst->door_control_leds_set(1, 0);
		}
		if(!strcmp(argv[i1], "--led3s"))
		{
			//ser_port_inst.led_set(3, 1);
			door_control_lib_inst->door_control_leds_set(3, 1);
		}
		if(!strcmp(argv[i1], "--led3c"))
		{
			//ser_port_inst.led_set(3, 0);
			door_control_lib_inst->door_control_leds_set(3, 0);
		}
		if(!strcmp(argv[i1], "--lock_open"))
		{
			if (door_control_lib_inst->door_control_lock_set <= 0)
				cout << " " << argv[i1] << " uninitialized" << endl;
			else
			{
				cout << "lock_open ";
				int ret_val = door_control_lib_inst->door_control_lock_set(1);
				cout << "result is " << ret_val << endl;
			}
		}
		if(!strcmp(argv[i1], "--lock_close"))
		{
			if (door_control_lib_inst->door_control_lock_set <= 0)
				cout << argv[i1] << " %s uninitialized" << endl;
			else
			{
				cout << "lock_close ";
				int ret_val = door_control_lib_inst->door_control_lock_set(0);
				cout << "result is " << ret_val << endl;
			}
		}
		if(!strcmp(argv[i1], "--modem_reset"))
		{
			if (door_control_lib_inst->door_control_modem_reset <= 0)
				cout << " " << argv[i1] << " uninitialized" << endl;
			else
			{
				cout << "modem_reset ";
				int ret_val = door_control_lib_inst->door_control_modem_reset();
				cout << "result is " << ret_val << endl;
			}
		}
		if(!strcmp(argv[i1], "--inps_r"))
		{
			if (door_control_lib_inst->door_control_inps_get <= 0)
				cout << " " << argv[i1] << " uninitialized" << endl;
			else
			{
				cout << "inps_r ";
				int ret_val = door_control_lib_inst->door_control_inps_get();
				cout << "result is " << ret_val << endl;
				cout << "inputs read " << ret_val << " 0b";
				for(int i2 = 3; i2 >= 0; i2--)
				{
					cout << ((ret_val >> i2) & 0x01);
				}
				cout << endl;
			}
		}
		if(!strcmp(argv[i1], "--read_key"))
		{
			char inp_str[32];
			cout << " read key" << endl;
			scanf("%s", inp_str);
		}
		if(!strcmp(argv[i1], "--d2xx_open"))
		{
			cout << "--d2xx_open found" << endl;
			int res_val = door_control_lib_inst->door_control_d2xx_dll_open();
			cout << "door_control_d2xx_dll_open ready" << endl;
			cout << " d2xx_open " << res_val << endl;
		}
		if(!strcmp(argv[i1], "--test_1"))
		{
			cout << "--test_1 found" << endl;
			door_control_lib_inst->door_control_ser_close();
			cout << " ser_close " << endl;
			cout << " finish " << door_control_lib_inst->door_control_finish() << endl;
			t_test_1_thread_ptr thread_1( new test_1_thread() );
			//strcpy(thread_1->ser_name, ser_name.c_str());
			thread_1->ser_name = ser_name;

			thread_1->ser_baud = ser_baud;

			thread_1->start();
			//test_thread test_thread_inst;
			//**************
			//test_thread_inst.test_thread();
			//int res_val = door_control_lib_inst->door_control_d2xx_dll_open();
			cout << "test_1 ready" << endl;
			//char inp_str[32];
			char inp_char = 0;
			cout << " read key" << endl;
			thread_1->door_control_lib_inst = door_control_lib_inst;
			//scanf("%s", inp_str);
			do
			{
				scanf("%c", &inp_char);
				if (inp_char == 'q')
				{
					thread_1->command = thread_1->quit;
				}
				if (inp_char == 't')
				{
					thread_1->state_timer = (thread_1->state_timer == 0)?1:0;
					cout << "timer " << thread_1->state_timer << endl;
				}
				if (inp_char == 'r')
				{
					thread_1->test_state = (thread_1->test_state == 0)?1:0;
					cout << "test_init_finish_state " << thread_1->test_state << endl;
				}
				if (inp_char == 'h')
				{
					cout << endl << "h - help, q - quit, t - on/off timer, r - on/off init-finish test" << endl;
				}
			}while (inp_char != 'q');
			for (int i1 = 1; i1 < 50 && thread_1->test_is_running == 1; i1++){Sleep(100);}
			pthread_exit(0);
			thread_1->~test_1_thread();
			//cout << " d2xx_open %d\n", res_val);
		}
		if(!strcmp(argv[i1], "--test_2"))
		{
			cout << "--test_2 found" << endl;
			door_control_lib_inst->door_control_ser_close();
			cout << " ser_close " << endl;
			cout << " finish " << door_control_lib_inst->door_control_finish() << endl;
			t_test_2_thread_ptr thread_2( new test_2_thread() );
			thread_2->ser_name = ser_name;
			thread_2->ser_baud = ser_baud;
			thread_2->sleep_delay = 100;
			thread_2->door_control_lib_inst = door_control_lib_inst;
			thread_2->start();
			cout << "test_2 ready" << endl;
			char inp_char = 0;
			cout << " read key" << endl;
			do
			{
				scanf("%c", &inp_char);
				if (inp_char == 'q')
				{
					thread_2->command = thread_2->quit;
				}
				if (inp_char == 't')
				{
					thread_2->state_timer = (thread_2->state_timer == 0)?1:0;
					cout << "timer " << thread_2->state_timer << endl;
				}
				if (inp_char == 'r')
				{
					thread_2->test_state = (thread_2->test_state == 0)?1:0;
					cout << "test_init_finish_state " << thread_2->test_state << endl;
				}
				if (inp_char == 'h')
				{
					cout << endl << "h - help, q - quit, t - on/off timer, r - on/off init-finish test" << endl;
				}
			}while (inp_char != 'q');
			for (int i1 = 1; i1 < 50 && thread_2->test_is_running == 1; i1++){Sleep(100);}
			pthread_exit(0);
			thread_2->~test_2_thread();
		}
		if(!strcmp(argv[i1], "--test_3"))
		{
			Sleep(100);
			cout << "--test_3 found" << endl;
			door_control_lib_inst->door_control_ser_close();
			cout << " ser_close " << endl;
			cout << " finish " << door_control_lib_inst->door_control_finish() << endl;
			t_Test_3_thread_ptr thread_3( new Test_3_thread() );
			//Sleep(100);
			thread_3->ser_name = ser_name;
			thread_3->ser_baud = ser_baud;
			thread_3->sleep_delay = 100;
			thread_3->door_control_lib_inst = door_control_lib_inst;
			thread_3->start();
			cout << "Sleep" << endl;
			Sleep(100);
			cout << "test_3 ready" << endl;
			char inp_char = 0;
			cout << " read key" << endl;
			do
			{
				scanf("%c", &inp_char);
				if (inp_char == 'q')
				{
					thread_3->command = thread_3->quit;
				}
				if (inp_char == 't')
				{
					thread_3->state_timer = (thread_3->state_timer == 0)?1:0;
					cout << "timer " << thread_3->state_timer << endl;
				}
				if (inp_char == 'r')
				{
					thread_3->test_state = (thread_3->test_state == 0)?1:0;
					cout << "test_socket " << thread_3->test_state << endl;
				}
				if (inp_char == 'h')
				{
					cout << endl << "h - help, q - quit, t - on/off timer, r - on/off init-finish test" << endl;
				}
			}while (inp_char != 'q');
			//cout << " next is for (...)" << endl;
			for (int i1 = 1; i1 < 50 && thread_3->test_is_running == 1; i1++){Sleep(100);}
			//cout << " next is pthread_exit" << endl;
			pthread_exit(0);
			//cout << "next is thread_3->~test_3_thread()" << endl;
			thread_3->~Test_3_thread();
			//cout << "next is thread_3->~test_3_thread() ready" << endl;
		}
		if(!strcmp(argv[i1], "--ser_close"))
		{
			if (door_control_lib_inst->door_control_ser_close <= 0)
				cout << " " << argv[i1] << " uninitialized" << endl;
			else
			{
				//ser_port_inst.close();
				door_control_lib_inst->door_control_ser_close();
				cout << " ser_close" << endl;
			}
		}
		if(!strcmp(argv[i1], "--finish"))
		{
			if (door_control_lib_inst->door_control_finish <= 0)
				cout << " " << argv[i1] << " uninitialized" << endl;
			else
			{
				cout << " finish " << door_control_lib_inst->door_control_finish() << endl;
			}
		}
		if(!strcmp(argv[i1], "--send_ping"))
		{
			//cout << "--send_ping" << endl;
			int ret_val = 0;
			char ping_addr_char[32];
			if((i1 + 1) <= argc)
			{
				i1++;
				//strcpy(ser_port_inst.name, argv[i1]);
				//door_control_lib_inst->door_control_ser_set_name(argv[i1]);
				//strcpy(ser_name, argv[i1]);
				//cout << "argv : " << argv[i1] << endl;
				ping_addr = string(argv[i1]);
			}
			//cout << " ser_name %s\n", ser_port_inst.name);
			cout << " ping_addr " << ping_addr << endl;
			strcpy(ping_addr_char, ping_addr.c_str());
			ret_val = door_control_lib_inst->send_ping(ping_addr_char);
			cout << " result " << ret_val << endl;
		}
		if(!strcmp(argv[i1], "--ping_start"))
		{
			//cout << "--send_ping" << endl;
			int ret_val = 0;
			char ping_addr_char[32];
			//cout << " ser_name %s\n", ser_port_inst.name);
			cout << " ping_start " << endl;
			ret_val = door_control_lib_inst->ping_start();
		}
		if(!strcmp(argv[i1], "--ping_stop"))
		{
			//cout << "--send_ping" << endl;
			int ret_val = 0;
			char ping_addr_char[32];
			//cout << " ser_name %s\n", ser_port_inst.name);
			cout << " ping_stop " << endl;
			ret_val = door_control_lib_inst->ping_stop();
		}
		if(!strcmp(argv[i1], "--ping_addr_add"))
		{
			int ret_val = 0;
			char ping_addr_char[32];
			if((i1 + 1) <= argc)
			{
				i1++;
				//strcpy(ser_port_inst.name, argv[i1]);
				//door_control_lib_inst->door_control_ser_set_name(argv[i1]);
				//strcpy(ser_name, argv[i1]);
				//cout << "argv : " << argv[i1] << endl;
				ping_addr = string(argv[i1]);
			}
			//cout << " ser_name %s\n", ser_port_inst.name);
			cout << " ping_addr " << ping_addr << endl;
			//strcpy(ping_addr_char, ping_addr.c_str());
			ret_val = door_control_lib_inst->ping_addr_add(ping_addr_char);
			cout << " result " << ret_val << endl;
		}
	}
	cout << "parser finish" << endl;
	door_control_lib_inst->dll_free();
	//if(door_control_lib_inst->h_ser_port_dll > (void*)HINSTANCE_ERROR) FreeLibrary(door_control_lib_inst->h_ser_port_dll);
	//printf(" port name %s\n", ser_port_inst.name);
	//printf(" port baud %d\n", ser_port_inst.get_baud());
	return 0;
}
